
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
  <head>
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>threading --- 基于线程的并发 &#8212; Python 3.7.3 文档</title>
    <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript" id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/language_data.js"></script>
    <script type="text/javascript" src="../_static/translations.js"></script>
    
    <script type="text/javascript" src="../_static/sidebar.js"></script>
    
    <link rel="search" type="application/opensearchdescription+xml"
          title="在 Python 3.7.3 文档 中搜索"
          href="../_static/opensearch.xml"/>
    <link rel="author" title="关于这些文档" href="../about.html" />
    <link rel="index" title="索引" href="../genindex.html" />
    <link rel="search" title="搜索" href="../search.html" />
    <link rel="copyright" title="版权所有" href="../copyright.html" />
    <link rel="next" title="multiprocessing --- Process-based parallelism" href="multiprocessing.html" />
    <link rel="prev" title="并发执行" href="concurrency.html" />
    <link rel="shortcut icon" type="image/png" href="../_static/py.png" />
    <link rel="canonical" href="https://docs.python.org/3/library/threading.html" />
    
    <script type="text/javascript" src="../_static/copybutton.js"></script>
    <script type="text/javascript" src="../_static/switchers.js"></script>
    
    
    
    <style>
      @media only screen {
        table.full-width-table {
            width: 100%;
        }
      }
    </style>
 

  </head><body>  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             accesskey="I">索引</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python 模块索引"
             >模块</a> |</li>
        <li class="right" >
          <a href="multiprocessing.html" title="multiprocessing --- Process-based parallelism"
             accesskey="N">下一页</a> |</li>
        <li class="right" >
          <a href="concurrency.html" title="并发执行"
             accesskey="P">上一页</a> |</li>
        <li><img src="../_static/py.png" alt=""
                 style="vertical-align: middle; margin-top: -1px"/></li>
        <li><a href="https://www.python.org/">Python</a> &#187;</li>
        <li>
          <span class="language_switcher_placeholder">zh_CN</span>
          <span class="version_switcher_placeholder">3.7.3</span>
          <a href="../index.html">文档</a> &#187;
        </li>

          <li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="concurrency.html" accesskey="U">并发执行</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="快速搜索" type="text" name="q" />
          <input type="submit" value="转向" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>    

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body" role="main">
            
  <div class="section" id="module-threading">
<span id="threading-thread-based-parallelism"></span><h1><a class="reference internal" href="#module-threading" title="threading: Thread-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code></a> --- 基于线程的并发<a class="headerlink" href="#module-threading" title="永久链接至标题">¶</a></h1>
<p><strong>源代码:</strong> <a class="reference external" href="https://github.com/python/cpython/tree/3.7/Lib/threading.py">Lib/threading.py</a></p>
<hr class="docutils" />
<p>这个模块在较低级的模块 <a class="reference internal" href="_thread.html#module-_thread" title="_thread: Low-level threading API."><code class="xref py py-mod docutils literal notranslate"><span class="pre">_thread</span></code></a> 基础上建立较高级的线程接口。参见： <a class="reference internal" href="queue.html#module-queue" title="queue: A synchronized queue class."><code class="xref py py-mod docutils literal notranslate"><span class="pre">queue</span></code></a>  模块。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.7 版更改: </span>这个模块曾经为可选项，但现在总是可用。</p>
</div>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last">虽然他们没有在下面列出，这个模块仍然支持Python 2.x系列的这个模块下以 <code class="docutils literal notranslate"><span class="pre">camelCase</span></code> （驼峰法）命名的方法和函数。</p>
</div>
<p>这个模块定义了以下函数：</p>
<dl class="function">
<dt id="threading.active_count">
<code class="descclassname">threading.</code><code class="descname">active_count</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.active_count" title="永久链接至目标">¶</a></dt>
<dd><p>返回当前存活的线程类 <a class="reference internal" href="#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">Thread</span></code></a> 对象。返回的计数等于 <a class="reference internal" href="#threading.enumerate" title="threading.enumerate"><code class="xref py py-func docutils literal notranslate"><span class="pre">enumerate()</span></code></a> 返回的列表长度。</p>
</dd></dl>

<dl class="function">
<dt id="threading.current_thread">
<code class="descclassname">threading.</code><code class="descname">current_thread</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.current_thread" title="永久链接至目标">¶</a></dt>
<dd><p>返回当前对应调用者的控制线程的 <a class="reference internal" href="#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">Thread</span></code></a> 对象。如果调用者的控制线程不是利用 <a class="reference internal" href="#module-threading" title="threading: Thread-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code></a> 创建，会返回一个功能受限的虚拟线程对象。</p>
</dd></dl>

<dl class="function">
<dt id="threading.get_ident">
<code class="descclassname">threading.</code><code class="descname">get_ident</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.get_ident" title="永久链接至目标">¶</a></dt>
<dd><p>返回当前线程的 “线程标识符”。它是一个非零的整数。它的值没有直接含义，主要是用作 magic cookie，比如作为含有线程相关数据的字典的索引。线程标识符可能会在线程退出，新线程创建时被复用。</p>
<div class="versionadded">
<p><span class="versionmodified">3.3 新版功能.</span></p>
</div>
</dd></dl>

<dl class="function">
<dt id="threading.enumerate">
<code class="descclassname">threading.</code><code class="descname">enumerate</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.enumerate" title="永久链接至目标">¶</a></dt>
<dd><p>以列表形式返回当前所有存活的 <a class="reference internal" href="#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">Thread</span></code></a> 对象。该列表包含守护线程， <a class="reference internal" href="#threading.current_thread" title="threading.current_thread"><code class="xref py py-func docutils literal notranslate"><span class="pre">current_thread()</span></code></a> 创建的虚拟线程对象和主线程。它包含了已终结的线程和尚未开始的线程。</p>
</dd></dl>

<dl class="function">
<dt id="threading.main_thread">
<code class="descclassname">threading.</code><code class="descname">main_thread</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.main_thread" title="永久链接至目标">¶</a></dt>
<dd><p>返回主 <a class="reference internal" href="#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">Thread</span></code></a> 对象。一般情况下，主线程是Python解释器开始时创建的线程。</p>
<div class="versionadded">
<p><span class="versionmodified">3.4 新版功能.</span></p>
</div>
</dd></dl>

<dl class="function">
<dt id="threading.settrace">
<code class="descclassname">threading.</code><code class="descname">settrace</code><span class="sig-paren">(</span><em>func</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.settrace" title="永久链接至目标">¶</a></dt>
<dd><p id="index-0">为所有 <a class="reference internal" href="#module-threading" title="threading: Thread-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code></a> 模块开始的线程设置追踪函数。在每个线程的 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法被调用前，<em>func</em> 会被传递给 <a class="reference internal" href="sys.html#sys.settrace" title="sys.settrace"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.settrace()</span></code></a> 。</p>
</dd></dl>

<dl class="function">
<dt id="threading.setprofile">
<code class="descclassname">threading.</code><code class="descname">setprofile</code><span class="sig-paren">(</span><em>func</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.setprofile" title="永久链接至目标">¶</a></dt>
<dd><p id="index-1">为所有 <a class="reference internal" href="#module-threading" title="threading: Thread-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code></a> 模块开始的线程设置性能测试函数。在每个线程的 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法被调用前，<em>func</em> 会被传递给 <a class="reference internal" href="sys.html#sys.setprofile" title="sys.setprofile"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.setprofile()</span></code></a> 。</p>
</dd></dl>

<dl class="function">
<dt id="threading.stack_size">
<code class="descclassname">threading.</code><code class="descname">stack_size</code><span class="sig-paren">(</span><span class="optional">[</span><em>size</em><span class="optional">]</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.stack_size" title="永久链接至目标">¶</a></dt>
<dd><p>返回创建线程时用的堆栈大小。可选参数 <em>size</em> 指定之后新建的线程的堆栈大小，而且一定要是0（根据平台或者默认配置）或者最小是32,768(32KiB)的一个正整数。如果 <em>size</em> 没有指定，默认是0。如果不支持改变线程堆栈大小，会抛出 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 错误。如果指定的堆栈大小不合法，会抛出 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 错误并且不会修改堆栈大小。32KiB是当前最小的能保证解释器有足够堆栈空间的堆栈大小。需要注意的是部分平台对于堆栈大小会有特定的限制，例如要求大于32KiB的堆栈大小或者需要根据系统内存页面的整数倍进行分配 - 应当查阅平台文档有关详细信息（4KiB页面比较普遍，在没有更具体信息的情况下，建议的方法是使用4096的倍数作为堆栈大小）。</p>
<p class="availability"><a class="reference internal" href="intro.html#availability"><span class="std std-ref">适用于</span></a>: Windows，具有 POSIX 线程的系统。</p>
</dd></dl>

<p>这个模块同时定义了以下常量：</p>
<dl class="data">
<dt id="threading.TIMEOUT_MAX">
<code class="descclassname">threading.</code><code class="descname">TIMEOUT_MAX</code><a class="headerlink" href="#threading.TIMEOUT_MAX" title="永久链接至目标">¶</a></dt>
<dd><p>阻塞函数（ <a class="reference internal" href="#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Lock.acquire()</span></code></a>, <a class="reference internal" href="#threading.RLock.acquire" title="threading.RLock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">RLock.acquire()</span></code></a>, <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Condition.wait()</span></code></a>, ...）中形参 <em>timeout</em> 允许的最大值。传入超过这个值的 timeout 会抛出 <a class="reference internal" href="exceptions.html#OverflowError" title="OverflowError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">OverflowError</span></code></a> 异常。</p>
<div class="versionadded">
<p><span class="versionmodified">3.2 新版功能.</span></p>
</div>
</dd></dl>

<p>这个模块定义了许多类，详见以下部分。</p>
<p>该模块的设计基于 Java的线程模型。 但是，在Java里面，锁和条件变量是每个对象的基础特性，而在Python里面，这些被独立成了单独的对象。 Python 的 <a class="reference internal" href="#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">Thread</span></code></a> 类只是 Java 的 Thread 类的一个子集；目前还没有优先级，没有线程组，线程还不能被销毁、停止、暂停、恢复或中断。 Java 的 Thread 类的静态方法在实现时会映射为模块级函数。</p>
<p>下列描述的方法都是自动执行的。</p>
<div class="section" id="thread-local-data">
<h2>线程本地数据<a class="headerlink" href="#thread-local-data" title="永久链接至标题">¶</a></h2>
<p>线程本地数据是特定线程的数据。管理线程本地数据，只需要创建一个 <a class="reference internal" href="#threading.local" title="threading.local"><code class="xref py py-class docutils literal notranslate"><span class="pre">local</span></code></a> （或者一个子类型）的实例并在实例中储存属性：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">mydata</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">local</span><span class="p">()</span>
<span class="n">mydata</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>在不同的线程中，实例的值会不同。</p>
<dl class="class">
<dt id="threading.local">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">local</code><a class="headerlink" href="#threading.local" title="永久链接至目标">¶</a></dt>
<dd><p>一个代表线程本地数据的类。</p>
<p>更多相关细节和大量示例，参见 <code class="xref py py-mod docutils literal notranslate"><span class="pre">_threading_local</span></code> 模块的文档。</p>
</dd></dl>

</div>
<div class="section" id="thread-objects">
<span id="id1"></span><h2>线程对象<a class="headerlink" href="#thread-objects" title="永久链接至标题">¶</a></h2>
<p>The <a class="reference internal" href="#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">Thread</span></code></a> class represents an activity that is run in a separate
thread of control.  There are two ways to specify the activity: by passing a
callable object to the constructor, or by overriding the <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a>
method in a subclass.  No other methods (except for the constructor) should be
overridden in a subclass.  In other words, <em>only</em>  override the
<code class="xref py py-meth docutils literal notranslate"><span class="pre">__init__()</span></code> and <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> methods of this class.</p>
<p>当线程对象一但被创建，其活动一定会因调用线程的 <a class="reference internal" href="#threading.Thread.start" title="threading.Thread.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a> 方法开始。这会在独立的控制线程调用 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法。</p>
<p>一旦线程活动开始，该线程会被认为是 '存活的' 。当它的 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法终结了（不管是正常的还是抛出未被处理的异常），就不是'存活的'。 <a class="reference internal" href="#threading.Thread.is_alive" title="threading.Thread.is_alive"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_alive()</span></code></a> 方法用于检查线程是否存活。</p>
<p>其他线程可以调用一个线程的 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 方法。这会阻塞调用该方法的线程，直到被调用 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 方法的线程终结。</p>
<p>线程有名字。名字可以传递给构造函数，也可以通过 <a class="reference internal" href="#threading.Thread.name" title="threading.Thread.name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">name</span></code></a> 属性读取或者修改。</p>
<p>一个线程可以被标记成一个 &quot;守护线程&quot; 。这个标志的意义是，只有守护线程都终结，整个Python程序才会退出。初始值继承于创建线程。这个标志可以通过 <a class="reference internal" href="#threading.Thread.daemon" title="threading.Thread.daemon"><code class="xref py py-attr docutils literal notranslate"><span class="pre">daemon</span></code></a> 特征属性或者 <em>守护</em> 构造函数参数来设置。</p>
<div class="admonition note">
<p class="first admonition-title">注解</p>
<p class="last">守护线程在程序关闭时会突然关闭。他们的资源（例如已经打开的文档，数据库事务等等）可能没有被正确释放。如果你想你的线程正常停止，设置他们成为非守护模式并且使用合适的信号机制，例如： <a class="reference internal" href="#threading.Event" title="threading.Event"><code class="xref py py-class docutils literal notranslate"><span class="pre">Event</span></code></a>。</p>
</div>
<p>有个 &quot;主线程&quot; 对象；这对应Python程序里面初始的控制线程。它不是一个守护线程。</p>
<p>&quot;虚拟线程对象&quot; 是可以被创建的。这些是对应于“外部线程”的线程对象，它们是在线程模块外部启动的控制线程，例如直接来自C代码。虚拟线程对象功能受限；他们总是被认为是存活的和守护模式，不能被 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 。因为无法检测外来线程的终结，它们永远不会被删除。</p>
<dl class="class">
<dt id="threading.Thread">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">Thread</code><span class="sig-paren">(</span><em>group=None</em>, <em>target=None</em>, <em>name=None</em>, <em>args=()</em>, <em>kwargs={}</em>, <em>*</em>, <em>daemon=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread" title="永久链接至目标">¶</a></dt>
<dd><p>调用这个构造函数时，必需带有关键字参数。参数如下：</p>
<p><em>group</em> 应该为 <code class="docutils literal notranslate"><span class="pre">None</span></code>；为了日后扩展 <code class="xref py py-class docutils literal notranslate"><span class="pre">ThreadGroup</span></code> 类实现而保留。</p>
<p><em>target</em> 是用于 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法调用的可调用对象。默认是 <code class="docutils literal notranslate"><span class="pre">None</span></code>，表示不需要调用任何方法。</p>
<p><em>name</em> 是线程名称。默认情况下，由 &quot;Thread-<em>N</em>&quot; 格式构成一个唯一的名称，其中 <em>N</em> 是小的十进制数。</p>
<p><em>args</em> 是用于调用目标函数的参数元组。默认是 <code class="docutils literal notranslate"><span class="pre">()</span></code>。</p>
<p><em>kwargs</em> 是用于调用目标函数的关键字参数字典。默认是 <code class="docutils literal notranslate"><span class="pre">{}</span></code>。</p>
<p>如果不是 <code class="docutils literal notranslate"><span class="pre">None</span></code>，线程将被显式的设置为 <em>守护模式</em>，不管该线程是否是守护模式。如果是 <code class="docutils literal notranslate"><span class="pre">None</span></code> (默认值)，线程将继承当前线程的守护模式属性。</p>
<p>如果子类型重载了构造函数，它一定要确保在做任何事前，先发起调用基类构造器(<code class="docutils literal notranslate"><span class="pre">Thread.__init__()</span></code>)。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.3 版更改: </span>加入 <em>daemon</em> 参数。</p>
</div>
<dl class="method">
<dt id="threading.Thread.start">
<code class="descname">start</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread.start" title="永久链接至目标">¶</a></dt>
<dd><p>开始线程活动。</p>
<p>它在一个线程里最多只能被调用一次。它安排对象的 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法在一个独立的控制进程中调用。</p>
<p>如果同一个线程对象中调用这个方法的次数大于一次，会抛出 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Thread.run">
<code class="descname">run</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread.run" title="永久链接至目标">¶</a></dt>
<dd><p>代表线程活动的方法。</p>
<p>你可以在子类型里重载这个方法。标准的 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法调用一个传递给对象构造函数的可调用对象，如果有，分别从 <em>args</em> 和 <em>kwargs</em> 参数中获取顺序和关键字参数。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Thread.join">
<code class="descname">join</code><span class="sig-paren">(</span><em>timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread.join" title="永久链接至目标">¶</a></dt>
<dd><p>等待，直到线程终结。这会阻塞调用这个方法的线程，直到被调用 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 的线程终结 -- 不管是正常终结还是抛出未处理异常 -- 或者直到发生超时，超时选项是可选的。</p>
<p>当 <em>timeout</em>&nbsp;参数存在而且不是 <code class="docutils literal notranslate"><span class="pre">None</span></code> 时，它应该是一个用于指定操作超时的以秒为单位的浮点数（或者分数）。因为 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 总是返回 <code class="docutils literal notranslate"><span class="pre">None</span></code> ，所以你一定要在 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 后调用 <a class="reference internal" href="#threading.Thread.is_alive" title="threading.Thread.is_alive"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_alive()</span></code></a> 才能判断是否发生超时 -- 如果线程仍然存货，则 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 超时。</p>
<p>当 <em>timeout</em> 参数不存在或者是 <code class="docutils literal notranslate"><span class="pre">None</span></code> ，这个操作会阻塞直到线程终结。</p>
<p>一个线程可以被 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 很多次。</p>
<p>如果尝试加入当前线程会导致死锁， <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 会引起 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a>  异常。如果尝试 <a class="reference internal" href="#threading.Thread.join" title="threading.Thread.join"><code class="xref py py-meth docutils literal notranslate"><span class="pre">join()</span></code></a> 一个尚未开始的线程，也会抛出相同的异常。</p>
</dd></dl>

<dl class="attribute">
<dt id="threading.Thread.name">
<code class="descname">name</code><a class="headerlink" href="#threading.Thread.name" title="永久链接至目标">¶</a></dt>
<dd><p>只用于识别的字符串。它没有语义。多个线程可以赋予相同的名称。 初始名称由构造函数设置。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Thread.getName">
<code class="descname">getName</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread.getName" title="永久链接至目标">¶</a></dt>
<dt id="threading.Thread.setName">
<code class="descname">setName</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread.setName" title="永久链接至目标">¶</a></dt>
<dd><p>旧的 <a class="reference internal" href="#threading.Thread.name" title="threading.Thread.name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">name</span></code></a> 取值/设值 API；直接当做特征属性使用它。</p>
</dd></dl>

<dl class="attribute">
<dt id="threading.Thread.ident">
<code class="descname">ident</code><a class="headerlink" href="#threading.Thread.ident" title="永久链接至目标">¶</a></dt>
<dd><p>这个线程的 '线程标识符'，如果线程尚未开始则为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 。这是个非零整数。参见  <a class="reference internal" href="#threading.get_ident" title="threading.get_ident"><code class="xref py py-func docutils literal notranslate"><span class="pre">get_ident()</span></code></a>&nbsp;函数。当一个线程退出而另外一个线程被创建，线程标识符会被复用。即使线程退出后，仍可得到标识符。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Thread.is_alive">
<code class="descname">is_alive</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread.is_alive" title="永久链接至目标">¶</a></dt>
<dd><p>返回线程是否存活。</p>
<p>当 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法刚开始直到 <a class="reference internal" href="#threading.Thread.run" title="threading.Thread.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">run()</span></code></a> 方法刚结束，这个方法返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。模块函数 <a class="reference internal" href="#threading.enumerate" title="threading.enumerate"><code class="xref py py-func docutils literal notranslate"><span class="pre">enumerate()</span></code></a> 返回包含所有存活线程的列表。</p>
</dd></dl>

<dl class="attribute">
<dt id="threading.Thread.daemon">
<code class="descname">daemon</code><a class="headerlink" href="#threading.Thread.daemon" title="永久链接至目标">¶</a></dt>
<dd><p>一个表示这个线程是（True）否（False）守护线程的布尔值。一定要在调用 <a class="reference internal" href="#threading.Thread.start" title="threading.Thread.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a> 前设置好，不然会抛出 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 。初始值继承于创建线程；主线程不是守护线程，因此主线程创建的所有线程默认都是 <a class="reference internal" href="#threading.Thread.daemon" title="threading.Thread.daemon"><code class="xref py py-attr docutils literal notranslate"><span class="pre">daemon</span></code></a> = <code class="docutils literal notranslate"><span class="pre">False</span></code>。</p>
<p>当没有存活的非守护线程时，整个Python程序才会退出。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Thread.isDaemon">
<code class="descname">isDaemon</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread.isDaemon" title="永久链接至目标">¶</a></dt>
<dt id="threading.Thread.setDaemon">
<code class="descname">setDaemon</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Thread.setDaemon" title="永久链接至目标">¶</a></dt>
<dd><p>旧的 <a class="reference internal" href="#threading.Thread.name" title="threading.Thread.name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">name</span></code></a> 取值/设值 API；建议直接当做特征属性使用它。</p>
</dd></dl>

</dd></dl>

<div class="impl-detail compound">
<p><strong>CPython implementation detail:</strong> CPython下，因为 <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">Global Interpreter Lock</span></a>，一个时刻只有一个线程可以执行Python代码（尽管如此，某些性能导向的库可能会克服这个限制）。如果你想让你的应用更好的利用多核计算机的计算性能，推荐你使用 <a class="reference internal" href="multiprocessing.html#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> 或者 <a class="reference internal" href="concurrent.futures.html#concurrent.futures.ProcessPoolExecutor" title="concurrent.futures.ProcessPoolExecutor"><code class="xref py py-class docutils literal notranslate"><span class="pre">concurrent.futures.ProcessPoolExecutor</span></code></a> 。但是如果你想同时运行多个I/O绑定任务，线程仍然是一个合适的模型。</p>
</div>
</div>
<div class="section" id="lock-objects">
<span id="id2"></span><h2>锁对象<a class="headerlink" href="#lock-objects" title="永久链接至标题">¶</a></h2>
<p>A primitive lock is a synchronization primitive that is not owned by a
particular thread when locked.  In Python, it is currently the lowest level
synchronization primitive available, implemented directly by the <a class="reference internal" href="_thread.html#module-_thread" title="_thread: Low-level threading API."><code class="xref py py-mod docutils literal notranslate"><span class="pre">_thread</span></code></a>
extension module.</p>
<p>A primitive lock is in one of two states, &quot;locked&quot; or &quot;unlocked&quot;. It is created
in the unlocked state.  It has two basic methods, <a class="reference internal" href="#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> and
<a class="reference internal" href="#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a>.  When the state is unlocked, <a class="reference internal" href="#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a>
changes the state to locked and returns immediately.  When the state is locked,
<a class="reference internal" href="#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> blocks until a call to <a class="reference internal" href="#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> in another
thread changes it to unlocked, then the <a class="reference internal" href="#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> call resets it
to locked and returns.  The <a class="reference internal" href="#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> method should only be
called in the locked state; it changes the state to unlocked and returns
immediately. If an attempt is made to release an unlocked lock, a
<a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> will be raised.</p>
<p>锁同样支持 <a class="reference internal" href="#with-locks"><span class="std std-ref">上下文管理协议</span></a>。</p>
<p>当多个线程在 <a class="reference internal" href="#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> 等待状态转变为未锁定被阻塞，然后 <a class="reference internal" href="#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> 重置状态为未锁定时，只有一个线程能继续执行；至于哪个等待线程继续执行没有定义，并且会根据实现而不同。</p>
<p>所有方法都是自动执行的。</p>
<dl class="class">
<dt id="threading.Lock">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">Lock</code><a class="headerlink" href="#threading.Lock" title="永久链接至目标">¶</a></dt>
<dd><p>实现原始锁对象的类。一旦一个线程获得一个锁，会阻塞随后尝试获得锁的线程，直到它被释放；任何线程都可以释放它。</p>
<p>需要注意的是 <code class="docutils literal notranslate"><span class="pre">Lock</span></code> 其实是一个工厂函数，返回平台支持的具体锁类中最有效的版本的实例。</p>
<dl class="method">
<dt id="threading.Lock.acquire">
<code class="descname">acquire</code><span class="sig-paren">(</span><em>blocking=True</em>, <em>timeout=-1</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Lock.acquire" title="永久链接至目标">¶</a></dt>
<dd><p>可以阻塞或非阻塞地获得锁。</p>
<p>当调用时参数 <em>blocking</em> 设置为 <code class="docutils literal notranslate"><span class="pre">True</span></code> （缺省值），阻塞直到锁被释放，然后将锁锁定并返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。</p>
<p>在参数 <em>blocking</em> 被设置为 <code class="docutils literal notranslate"><span class="pre">False</span></code> 的情况下调用，将不会发生阻塞。如果调用时 <em>blocking</em> 设为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 会阻塞，并立即返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> ；否则，将锁锁定并返回 <code class="docutils literal notranslate"><span class="pre">True</span></code>。</p>
<p>When invoked with the floating-point <em>timeout</em> argument set to a positive
value, block for at most the number of seconds specified by <em>timeout</em>
and as long as the lock cannot be acquired.  A <em>timeout</em> argument of <code class="docutils literal notranslate"><span class="pre">-1</span></code>
specifies an unbounded wait.  It is forbidden to specify a <em>timeout</em>
when <em>blocking</em> is false.</p>
<p>如果成功获得锁，则返回 <code class="docutils literal notranslate"><span class="pre">True</span></code>，否则返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> (例如发生 <em>超时</em> 的时候)。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.2 版更改: </span>新的 <em>timeout</em> 形参。</p>
</div>
<div class="versionchanged">
<p><span class="versionmodified">在 3.2 版更改: </span>现在如果底层线程实现支持，则可以通过POSIX上的信号中断锁的获取。</p>
</div>
</dd></dl>

<dl class="method">
<dt id="threading.Lock.release">
<code class="descname">release</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Lock.release" title="永久链接至目标">¶</a></dt>
<dd><p>释放一个锁。这个方法可以在任何线程中调用，不单指获得锁的线程。</p>
<p>当锁被锁定，将它重置为未锁定，并返回。如果其他线程正在等待这个锁解锁而被阻塞，只允许其中一个允许。</p>
<p>在未锁定的锁调用时，会引发 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 异常。</p>
<p>没有返回值。</p>
</dd></dl>

</dd></dl>

</div>
<div class="section" id="rlock-objects">
<span id="id3"></span><h2>递归锁对象<a class="headerlink" href="#rlock-objects" title="永久链接至标题">¶</a></h2>
<p>A reentrant lock is a synchronization primitive that may be acquired multiple
times by the same thread.  Internally, it uses the concepts of &quot;owning thread&quot;
and &quot;recursion level&quot; in addition to the locked/unlocked state used by primitive
locks.  In the locked state, some thread owns the lock; in the unlocked state,
no thread owns it.</p>
<p>To lock the lock, a thread calls its <a class="reference internal" href="#threading.RLock.acquire" title="threading.RLock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> method; this
returns once the thread owns the lock.  To unlock the lock, a thread calls
its <a class="reference internal" href="#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> method. <a class="reference internal" href="#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a>/<a class="reference internal" href="#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a>
call pairs may be nested; only the final <a class="reference internal" href="#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> (the
<a class="reference internal" href="#threading.Lock.release" title="threading.Lock.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> of the outermost pair) resets the lock to unlocked and
allows another thread blocked in <a class="reference internal" href="#threading.Lock.acquire" title="threading.Lock.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> to proceed.</p>
<p>递归锁也支持 <a class="reference internal" href="#with-locks"><span class="std std-ref">上下文管理协议</span></a>。</p>
<dl class="class">
<dt id="threading.RLock">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">RLock</code><a class="headerlink" href="#threading.RLock" title="永久链接至目标">¶</a></dt>
<dd><p>This class implements reentrant lock objects.  A reentrant lock must be
released by the thread that acquired it.  Once a thread has acquired a
reentrant lock, the same thread may acquire it again without blocking; the
thread must release it once for each time it has acquired it.</p>
<p>需要注意的是 <code class="docutils literal notranslate"><span class="pre">RLock</span></code> 其实是一个工厂函数，返回平台支持的具体递归锁类中最有效的版本的实例。</p>
<dl class="method">
<dt id="threading.RLock.acquire">
<code class="descname">acquire</code><span class="sig-paren">(</span><em>blocking=True</em>, <em>timeout=-1</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.RLock.acquire" title="永久链接至目标">¶</a></dt>
<dd><p>可以阻塞或非阻塞地获得锁。</p>
<p>When invoked without arguments: if this thread already owns the lock, increment
the recursion level by one, and return immediately.  Otherwise, if another
thread owns the lock, block until the lock is unlocked.  Once the lock is
unlocked (not owned by any thread), then grab ownership, set the recursion level
to one, and return.  If more than one thread is blocked waiting until the lock
is unlocked, only one at a time will be able to grab ownership of the lock.
There is no return value in this case.</p>
<p>当调用时参数 <em>blocking</em> 设置为 <code class="docutils literal notranslate"><span class="pre">True</span></code> ，和没带参数调用一样做同样的事，然后返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。</p>
<p>When invoked with the <em>blocking</em> argument set to false, do not block.  If a call
without an argument would block, return false immediately; otherwise, do the
same thing as when called without arguments, and return true.</p>
<p>When invoked with the floating-point <em>timeout</em> argument set to a positive
value, block for at most the number of seconds specified by <em>timeout</em>
and as long as the lock cannot be acquired.  Return true if the lock has
been acquired, false if the timeout has elapsed.</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.2 版更改: </span>新的 <em>timeout</em> 形参。</p>
</div>
</dd></dl>

<dl class="method">
<dt id="threading.RLock.release">
<code class="descname">release</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.RLock.release" title="永久链接至目标">¶</a></dt>
<dd><p>Release a lock, decrementing the recursion level.  If after the decrement it is
zero, reset the lock to unlocked (not owned by any thread), and if any other
threads are blocked waiting for the lock to become unlocked, allow exactly one
of them to proceed.  If after the decrement the recursion level is still
nonzero, the lock remains locked and owned by the calling thread.</p>
<p>只有当前线程拥有锁才能调用这个方法。如果锁被释放后调用这个方法，会引起 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 异常。</p>
<p>没有返回值。</p>
</dd></dl>

</dd></dl>

</div>
<div class="section" id="condition-objects">
<span id="id4"></span><h2>条件对象<a class="headerlink" href="#condition-objects" title="永久链接至标题">¶</a></h2>
<p>条件变量总是与某种类型的锁对象相关联，锁对象可以通过传入获得，或者在缺省的情况下自动创建。当多个条件变量需要共享同一个锁时，传入一个锁很有用。锁是条件对象的一部分，你不必单独地跟踪它。</p>
<p>条件变量服从 <a class="reference internal" href="#with-locks"><span class="std std-ref">上下文管理协议</span></a>：使用 <code class="docutils literal notranslate"><span class="pre">with</span></code> 语句会在它包围的代码块内获取关联的锁。 <a class="reference internal" href="#threading.Condition.acquire" title="threading.Condition.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> 和 <a class="reference internal" href="#threading.Condition.release" title="threading.Condition.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> 方法也能调用关联锁的相关方法。</p>
<p>其它方法必须在持有关联的锁的情况下调用。 <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法释放锁，然后阻塞直到其它线程调用 <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 方法或 <a class="reference internal" href="#threading.Condition.notify_all" title="threading.Condition.notify_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify_all()</span></code></a> 方法唤醒它。一旦被唤醒， <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法重新获取锁并返回。它也可以指定超时时间。</p>
<p>The <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> method wakes up one of the threads waiting for
the condition variable, if any are waiting.  The <a class="reference internal" href="#threading.Condition.notify_all" title="threading.Condition.notify_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify_all()</span></code></a>
method wakes up all threads waiting for the condition variable.</p>
<p>注意： <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 方法和 <a class="reference internal" href="#threading.Condition.notify_all" title="threading.Condition.notify_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify_all()</span></code></a> 方法并不会释放锁，这意味着被唤醒的线程不会立即从它们的 <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法调用中返回，而是会在调用了 <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 方法或 <a class="reference internal" href="#threading.Condition.notify_all" title="threading.Condition.notify_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify_all()</span></code></a> 方法的线程最终放弃了锁的所有权后返回。</p>
<p>使用条件变量的典型编程风格是将锁用于同步某些共享状态的权限，那些对状态的某些特定改变感兴趣的线程，它们重复调用 <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法，直到看到所期望的改变发生；而对于修改状态的线程，它们将当前状态改变为可能是等待者所期待的新状态后，调用 <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 方法或者 <a class="reference internal" href="#threading.Condition.notify_all" title="threading.Condition.notify_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify_all()</span></code></a> 方法。例如，下面的代码是一个通用的无限缓冲区容量的生产者-消费者情形：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># Consume one item</span>
<span class="k">with</span> <span class="n">cv</span><span class="p">:</span>
    <span class="k">while</span> <span class="ow">not</span> <span class="n">an_item_is_available</span><span class="p">():</span>
        <span class="n">cv</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
    <span class="n">get_an_available_item</span><span class="p">()</span>

<span class="c1"># Produce one item</span>
<span class="k">with</span> <span class="n">cv</span><span class="p">:</span>
    <span class="n">make_an_item_available</span><span class="p">()</span>
    <span class="n">cv</span><span class="o">.</span><span class="n">notify</span><span class="p">()</span>
</pre></div>
</div>
<p>使用 <code class="docutils literal notranslate"><span class="pre">while</span></code> 循环检查所要求的条件成立与否是有必要的，因为 <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法可能要经过不确定长度的时间后才会返回，而此时导致 <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 方法调用的那个条件可能已经不再成立。这是多线程编程所固有的问题。 <a class="reference internal" href="#threading.Condition.wait_for" title="threading.Condition.wait_for"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait_for()</span></code></a>&nbsp;方法可自动化条件检查，并简化超时计算。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># Consume an item</span>
<span class="k">with</span> <span class="n">cv</span><span class="p">:</span>
    <span class="n">cv</span><span class="o">.</span><span class="n">wait_for</span><span class="p">(</span><span class="n">an_item_is_available</span><span class="p">)</span>
    <span class="n">get_an_available_item</span><span class="p">()</span>
</pre></div>
</div>
<p>选择 <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 还是 <a class="reference internal" href="#threading.Condition.notify_all" title="threading.Condition.notify_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify_all()</span></code></a> ，取决于一次状态改变是只能被一个还是能被多个等待线程所用。例如在一个典型的生产者-消费者情形中，添加一个项目到缓冲区只需唤醒一个消费者线程。</p>
<dl class="class">
<dt id="threading.Condition">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">Condition</code><span class="sig-paren">(</span><em>lock=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Condition" title="永久链接至目标">¶</a></dt>
<dd><p>实现条件变量对象的类。一个条件变量对象允许一个或多个线程在被其它线程所通知之前进行等待。</p>
<p>如果给出了非 <code class="docutils literal notranslate"><span class="pre">None</span></code> 的 <em>lock</em> 参数，则它必须为 <a class="reference internal" href="#threading.Lock" title="threading.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 或者 <a class="reference internal" href="#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 对象，并且它将被用作底层锁。否则，将会创建新的 <a class="reference internal" href="#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 对象，并将其用作底层锁。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.3 版更改: </span>从工厂函数变为类。</p>
</div>
<dl class="method">
<dt id="threading.Condition.acquire">
<code class="descname">acquire</code><span class="sig-paren">(</span><em>*args</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Condition.acquire" title="永久链接至目标">¶</a></dt>
<dd><p>请求底层锁。此方法调用底层锁的相应方法，返回值是底层锁相应方法的返回值。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Condition.release">
<code class="descname">release</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Condition.release" title="永久链接至目标">¶</a></dt>
<dd><p>释放底层锁。此方法调用底层锁的相应方法。没有返回值。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Condition.wait">
<code class="descname">wait</code><span class="sig-paren">(</span><em>timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Condition.wait" title="永久链接至目标">¶</a></dt>
<dd><p>等待直到被通知或发生超时。如果线程在调用此方法时没有获得锁，将会引发 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 异常。</p>
<p>这个方法释放底层锁，然后阻塞，直到在另外一个线程中调用同一个条件变量的 <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 或 <a class="reference internal" href="#threading.Condition.notify_all" title="threading.Condition.notify_all"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify_all()</span></code></a> 唤醒它，或者直到可选的超时发生。一旦被唤醒或者超时，它重新获得锁并返回。</p>
<p>当提供了 <em>timeout</em> 参数且不是 <code class="docutils literal notranslate"><span class="pre">None</span></code> 时，它应该是一个浮点数，代表操作的超时时间，以秒为单位（可以为小数）。</p>
<p>当底层锁是个 <a class="reference internal" href="#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> ，不会使用它的 <a class="reference internal" href="#threading.Condition.release" title="threading.Condition.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> 方法释放锁，因为当它被递归多次获取时，实际上可能无法解锁。相反，使用了 <a class="reference internal" href="#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 类的内部接口，即使多次递归获取它也能解锁它。 然后，在重新获取锁时，使用另一个内部接口来恢复递归级别。</p>
<p>返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> ，除非提供的 <em>timeout</em> 过期，这种情况下返回 <code class="docutils literal notranslate"><span class="pre">False</span></code>。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.2 版更改: </span>很明显，方法总是返回 <code class="docutils literal notranslate"><span class="pre">None</span></code>。</p>
</div>
</dd></dl>

<dl class="method">
<dt id="threading.Condition.wait_for">
<code class="descname">wait_for</code><span class="sig-paren">(</span><em>predicate</em>, <em>timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Condition.wait_for" title="永久链接至目标">¶</a></dt>
<dd><p>等待，直到条件计算为真。 <em>predicate</em> 应该是一个可调用对象而且它的返回值可被解释为一个布尔值。可以提供 <em>timeout</em> 参数给出最大等待时间。</p>
<p>这个实用方法会重复地调用 <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 直到满足判断式或者发生超时。返回值是判断式最后一个返回值，而且如果方法发生超时会返回 <code class="docutils literal notranslate"><span class="pre">False</span></code> 。</p>
<p>忽略超时功能，调用此方法大致相当于编写:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">while</span> <span class="ow">not</span> <span class="n">predicate</span><span class="p">():</span>
    <span class="n">cv</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
</pre></div>
</div>
<p>因此，规则同样适用于 <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> ：锁必须在被调用时保持获取，并在返回时重新获取。 随着锁定执行判断式。</p>
<div class="versionadded">
<p><span class="versionmodified">3.2 新版功能.</span></p>
</div>
</dd></dl>

<dl class="method">
<dt id="threading.Condition.notify">
<code class="descname">notify</code><span class="sig-paren">(</span><em>n=1</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Condition.notify" title="永久链接至目标">¶</a></dt>
<dd><p>默认唤醒一个等待这个条件的线程。如果调用线程在没有获得锁的情况下调用这个方法，会引发 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 异常。</p>
<p>这个方法唤醒最多 <em>n</em> 个正在等待这个条件变量的线程；如果没有线程在等待，这是一个空操作。</p>
<p>当前实现中，如果至少有 <em>n</em> 个线程正在等待，准确唤醒 <em>n</em> 个线程。但是依赖这个行为并不安全。未来，优化的实现有时会唤醒超过 <em>n</em> 个线程。</p>
<p>注意：被唤醒的线程实际上不会返回它调用的 <a class="reference internal" href="#threading.Condition.wait" title="threading.Condition.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> ，直到它可以重新获得锁。因为 <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 不会释放锁，只有它的调用者应该这样做。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Condition.notify_all">
<code class="descname">notify_all</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Condition.notify_all" title="永久链接至目标">¶</a></dt>
<dd><p>唤醒所有正在等待这个条件的线程。这个方法行为与 <a class="reference internal" href="#threading.Condition.notify" title="threading.Condition.notify"><code class="xref py py-meth docutils literal notranslate"><span class="pre">notify()</span></code></a> 相似，但并不只唤醒单一线程，而是唤醒所有等待线程。如果调用线程在调用这个方法时没有获得锁，会引发 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 异常。</p>
</dd></dl>

</dd></dl>

</div>
<div class="section" id="semaphore-objects">
<span id="id5"></span><h2>信号量对象<a class="headerlink" href="#semaphore-objects" title="永久链接至标题">¶</a></h2>
<p>这是计算机科学史上最古老的同步原语之一，早期的荷兰科学家 Edsger W. Dijkstra 发明了它。（他使用名称 <code class="docutils literal notranslate"><span class="pre">P()</span></code> 和 <code class="docutils literal notranslate"><span class="pre">V()</span></code> 而不是 <a class="reference internal" href="#threading.Semaphore.acquire" title="threading.Semaphore.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> 和 <a class="reference internal" href="#threading.Semaphore.release" title="threading.Semaphore.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> ）。</p>
<p>一个信号量管理一个内部计数器，该计数器因 <a class="reference internal" href="#threading.Semaphore.acquire" title="threading.Semaphore.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> 方法的调用而递减，因 <a class="reference internal" href="#threading.Semaphore.release" title="threading.Semaphore.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> 方法的调用而递增。 计数器的值永远不会小于零；当 <a class="reference internal" href="#threading.Semaphore.acquire" title="threading.Semaphore.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> 方法发现计数器为零时，将会阻塞，直到其它线程调用 <a class="reference internal" href="#threading.Semaphore.release" title="threading.Semaphore.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> 方法。</p>
<p>信号量对象也支持 <a class="reference internal" href="#with-locks"><span class="std std-ref">上下文管理协议</span></a> 。</p>
<dl class="class">
<dt id="threading.Semaphore">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">Semaphore</code><span class="sig-paren">(</span><em>value=1</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Semaphore" title="永久链接至目标">¶</a></dt>
<dd><p>该类实现信号量对象。信号量对象管理一个原子性的计数器，代表 <a class="reference internal" href="#threading.Semaphore.release" title="threading.Semaphore.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> 方法的调用次数减去 <a class="reference internal" href="#threading.Semaphore.acquire" title="threading.Semaphore.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> 的调用次数再加上一个初始值。如果需要， <a class="reference internal" href="#threading.Semaphore.acquire" title="threading.Semaphore.acquire"><code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code></a> 方法将会阻塞直到可以返回而不会使得计数器变成负数。在没有显式给出 <em>value</em> 的值时，默认为1。</p>
<p>可选参数 <em>value</em> 赋予内部计数器初始值，默认值为 <code class="docutils literal notranslate"><span class="pre">1</span></code> 。如果 <em>value</em> 被赋予小于0的值，将会引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 异常。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.3 版更改: </span>从工厂函数变为类。</p>
</div>
<dl class="method">
<dt id="threading.Semaphore.acquire">
<code class="descname">acquire</code><span class="sig-paren">(</span><em>blocking=True</em>, <em>timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Semaphore.acquire" title="永久链接至目标">¶</a></dt>
<dd><p>获取一个信号量。</p>
<p>在不带参数的情况下调用时：</p>
<ul class="simple">
<li>如果在进入时，内部计数器的值大于0，将其减1并立即返回true。</li>
<li>如果在进入时，内部计数器的值为0，将会阻塞直到被 <a class="reference internal" href="#threading.Semaphore.release" title="threading.Semaphore.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> 方法的调用唤醒。一旦被唤醒（并且计数器值大于0），将计数器值减少1并返回true。线程会被每次 <a class="reference internal" href="#threading.Semaphore.release" title="threading.Semaphore.release"><code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code></a> 方法的调用唤醒。线程被唤醒的次序是不确定的。</li>
</ul>
<p>在参数 <em>blocking</em> 被设置为false的情况下调用，将不会发生阻塞。如果不带参数的调用会发生阻塞的话，带参数的调用在相同情况下将会立即返回false。否则，执行和不带参数的调用一样的操作并返回true。</p>
<p>当参数 <em>timeout</em> 不为 <code class="docutils literal notranslate"><span class="pre">None</span></code> 时，将最多阻塞 <em>timeout</em> 秒。如果未能在时间间隔内成功获取信号量，将返回false，否则返回true。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.2 版更改: </span>新的 <em>timeout</em> 形参。</p>
</div>
</dd></dl>

<dl class="method">
<dt id="threading.Semaphore.release">
<code class="descname">release</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Semaphore.release" title="永久链接至目标">¶</a></dt>
<dd><p>释放一个信号量，将内部计数器的值增加1。当计数器原先的值为0且有其它线程正在等待它再次大于0时，唤醒正在等待的线程。</p>
</dd></dl>

</dd></dl>

<dl class="class">
<dt id="threading.BoundedSemaphore">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">BoundedSemaphore</code><span class="sig-paren">(</span><em>value=1</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.BoundedSemaphore" title="永久链接至目标">¶</a></dt>
<dd><p>该类实现有界信号量。有界信号量通过检查以确保它当前的值不会超过初始值。如果超过了初始值，将会引发 <a class="reference internal" href="exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> 异常。在大多情况下，信号量用于保护数量有限的资源。如果信号量被释放的次数过多，则表明出现了错误。没有指定时， <em>value</em> 的值默认为1。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.3 版更改: </span>从工厂函数变为类。</p>
</div>
</dd></dl>

<div class="section" id="semaphore-example">
<span id="semaphore-examples"></span><h3><a class="reference internal" href="#threading.Semaphore" title="threading.Semaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">Semaphore</span></code></a> 例子<a class="headerlink" href="#semaphore-example" title="永久链接至标题">¶</a></h3>
<p>信号量通常用于保护数量有限的资源，例如数据库服务器。在资源数量固定的任何情况下，都应该使用有界信号量。在生成任何工作线程前，应该在主线程中初始化信号量。</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">maxconnections</span> <span class="o">=</span> <span class="mi">5</span>
<span class="c1"># ...</span>
<span class="n">pool_sema</span> <span class="o">=</span> <span class="n">BoundedSemaphore</span><span class="p">(</span><span class="n">value</span><span class="o">=</span><span class="n">maxconnections</span><span class="p">)</span>
</pre></div>
</div>
<p>工作线程生成后，当需要连接服务器时，这些线程将调用信号量的 acquire 和 release 方法：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">pool_sema</span><span class="p">:</span>
    <span class="n">conn</span> <span class="o">=</span> <span class="n">connectdb</span><span class="p">()</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="c1"># ... use connection ...</span>
    <span class="k">finally</span><span class="p">:</span>
        <span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>使用有界信号量能减少这种编程错误：信号量的释放次数多于其请求次数。</p>
</div>
</div>
<div class="section" id="event-objects">
<span id="id6"></span><h2>事件对象<a class="headerlink" href="#event-objects" title="永久链接至标题">¶</a></h2>
<p>这是线程之间通信的最简单机制之一：一个线程发出事件信号，而其他线程等待该信号。</p>
<p>一个事件对象管理一个内部标志，调用 <a class="reference internal" href="#threading.Event.set" title="threading.Event.set"><code class="xref py py-meth docutils literal notranslate"><span class="pre">set()</span></code></a> 方法可将其设置为true，调用  <a class="reference internal" href="#threading.Event.clear" title="threading.Event.clear"><code class="xref py py-meth docutils literal notranslate"><span class="pre">clear()</span></code></a> 方法可将其设置为false，调用 <a class="reference internal" href="#threading.Event.wait" title="threading.Event.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法将进入阻塞直到标志为true。</p>
<dl class="class">
<dt id="threading.Event">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">Event</code><a class="headerlink" href="#threading.Event" title="永久链接至目标">¶</a></dt>
<dd><p>实现事件对象的类。事件对象管理一个内部标志，调用 <a class="reference internal" href="#threading.Event.set" title="threading.Event.set"><code class="xref py py-meth docutils literal notranslate"><span class="pre">set()</span></code></a> 方法可将其设置为true。调用  <a class="reference internal" href="#threading.Event.clear" title="threading.Event.clear"><code class="xref py py-meth docutils literal notranslate"><span class="pre">clear()</span></code></a> 方法可将其设置为false。调用 <a class="reference internal" href="#threading.Event.wait" title="threading.Event.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法将进入阻塞直到标志为true。这个标志初始时为false。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.3 版更改: </span>从工厂函数变为类。</p>
</div>
<dl class="method">
<dt id="threading.Event.is_set">
<code class="descname">is_set</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Event.is_set" title="永久链接至目标">¶</a></dt>
<dd><p>当且仅当内部标志为true时返回true。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Event.set">
<code class="descname">set</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Event.set" title="永久链接至目标">¶</a></dt>
<dd><p>将内部标志设置为true。所有正在等待这个事件的线程将被唤醒。当标志为true时，调用 <a class="reference internal" href="#threading.Event.wait" title="threading.Event.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法的线程不会被被阻塞。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Event.clear">
<code class="descname">clear</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Event.clear" title="永久链接至目标">¶</a></dt>
<dd><p>将内部标志设置为false。之后调用 <a class="reference internal" href="#threading.Event.wait" title="threading.Event.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法的线程将会被阻塞，直到调用 <a class="reference internal" href="#threading.Event.set" title="threading.Event.set"><code class="xref py py-meth docutils literal notranslate"><span class="pre">set()</span></code></a> 方法将内部标志再次设置为true。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Event.wait">
<code class="descname">wait</code><span class="sig-paren">(</span><em>timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Event.wait" title="永久链接至目标">¶</a></dt>
<dd><p>阻塞线程直到内部变量为true。如果调用时内部标志为true，将立即返回。否则将阻塞线程，直到调用 <a class="reference internal" href="#threading.Event.set" title="threading.Event.set"><code class="xref py py-meth docutils literal notranslate"><span class="pre">set()</span></code></a> 方法将标志设置为true或者发生可选的超时。</p>
<p>当提供了timeout参数且不是 <code class="docutils literal notranslate"><span class="pre">None</span></code> 时，它应该是一个浮点数，代表操作的超时时间，以秒为单位（可以为小数）。</p>
<p>当内部标志在调用wait进入阻塞后被设置为true，或者调用wait时已经被设置为true时，方法返回true。 也就是说，除非设定了超时且发生了超时的情况下将会返回false，其他情况该方法都将返回 <code class="docutils literal notranslate"><span class="pre">True</span></code> 。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.1 版更改: </span>很明显，方法总是返回 <code class="docutils literal notranslate"><span class="pre">None</span></code>。</p>
</div>
</dd></dl>

</dd></dl>

</div>
<div class="section" id="timer-objects">
<span id="id7"></span><h2>定时器对象<a class="headerlink" href="#timer-objects" title="永久链接至标题">¶</a></h2>
<p>此类表示一个操作应该在等待一定的时间之后运行 --- 相当于一个定时器。 <a class="reference internal" href="#threading.Timer" title="threading.Timer"><code class="xref py py-class docutils literal notranslate"><span class="pre">Timer</span></code></a> 类是 <a class="reference internal" href="#threading.Thread" title="threading.Thread"><code class="xref py py-class docutils literal notranslate"><span class="pre">Thread</span></code></a> 类的子类，因此可以像一个自定义线程一样工作。</p>
<p>与线程一样，通过调用 <code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code> 方法启动定时器。而 <a class="reference internal" href="#threading.Timer.cancel" title="threading.Timer.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">cancel()</span></code></a> 方法可以停止计时器（在计时结束前）， 定时器在执行其操作之前等待的时间间隔可能与用户指定的时间间隔不完全相同。</p>
<p>例如:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;hello, world&quot;</span><span class="p">)</span>

<span class="n">t</span> <span class="o">=</span> <span class="n">Timer</span><span class="p">(</span><span class="mf">30.0</span><span class="p">,</span> <span class="n">hello</span><span class="p">)</span>
<span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>  <span class="c1"># after 30 seconds, &quot;hello, world&quot; will be printed</span>
</pre></div>
</div>
<dl class="class">
<dt id="threading.Timer">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">Timer</code><span class="sig-paren">(</span><em>interval</em>, <em>function</em>, <em>args=None</em>, <em>kwargs=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Timer" title="永久链接至目标">¶</a></dt>
<dd><p>创建一个定时器，在经过 <em>interval</em> 秒的间隔事件后，将会用参数 <em>args</em> 和关键字参数 <em>kwargs</em> 调用 <em>function</em>。如果 <em>args</em> 为 <code class="docutils literal notranslate"><span class="pre">None</span></code> （默认值），则会使用一个空列表。如果 <em>kwargs</em> 为 <code class="docutils literal notranslate"><span class="pre">None</span></code> （默认值），则会使用一个空字典。</p>
<div class="versionchanged">
<p><span class="versionmodified">在 3.3 版更改: </span>从工厂函数变为类。</p>
</div>
<dl class="method">
<dt id="threading.Timer.cancel">
<code class="descname">cancel</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Timer.cancel" title="永久链接至目标">¶</a></dt>
<dd><p>停止定时器并取消执行计时器将要执行的操作。仅当计时器仍处于等待状态时有效。</p>
</dd></dl>

</dd></dl>

</div>
<div class="section" id="barrier-objects">
<h2>栅栏对象<a class="headerlink" href="#barrier-objects" title="永久链接至标题">¶</a></h2>
<div class="versionadded">
<p><span class="versionmodified">3.2 新版功能.</span></p>
</div>
<p>栅栏类提供一个简单的同步原语，用于应对固定数量的线程需要彼此相互等待的情况。线程调用 <a class="reference internal" href="#threading.Barrier.wait" title="threading.Barrier.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法后将阻塞，直到所有线程都调用了 <a class="reference internal" href="#threading.Barrier.wait" title="threading.Barrier.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法。此时所有线程将被同时释放。</p>
<p>栅栏对象可以被多次使用，但进程的数量不能改变。</p>
<p>这是一个使用简便的方法实现客户端进程与服务端进程同步的例子：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="n">Barrier</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">server</span><span class="p">():</span>
    <span class="n">start_server</span><span class="p">()</span>
    <span class="n">b</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">connection</span> <span class="o">=</span> <span class="n">accept_connection</span><span class="p">()</span>
        <span class="n">process_server_connection</span><span class="p">(</span><span class="n">connection</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">client</span><span class="p">():</span>
    <span class="n">b</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">connection</span> <span class="o">=</span> <span class="n">make_connection</span><span class="p">()</span>
        <span class="n">process_client_connection</span><span class="p">(</span><span class="n">connection</span><span class="p">)</span>
</pre></div>
</div>
<dl class="class">
<dt id="threading.Barrier">
<em class="property">class </em><code class="descclassname">threading.</code><code class="descname">Barrier</code><span class="sig-paren">(</span><em>parties</em>, <em>action=None</em>, <em>timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Barrier" title="永久链接至目标">¶</a></dt>
<dd><p>创建一个需要 <em>parties</em> 个线程的栅栏对象。如果提供了可调用的 <em>action</em> 参数，它会在所有线程被释放时在其中一个线程中自动调用。 <em>timeout</em> 是默认的超时时间，如果没有在 <a class="reference internal" href="#threading.Barrier.wait" title="threading.Barrier.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法中指定超时时间的话。</p>
<dl class="method">
<dt id="threading.Barrier.wait">
<code class="descname">wait</code><span class="sig-paren">(</span><em>timeout=None</em><span class="sig-paren">)</span><a class="headerlink" href="#threading.Barrier.wait" title="永久链接至目标">¶</a></dt>
<dd><p>冲出栅栏。当栅栏中所有线程都已经调用了这个函数，它们将同时被释放。如果提供了 <em>timeout</em> 参数，这里的 <em>timeout</em> 参数优先于创建栅栏对象时提供的 <em>timeout</em> 参数。</p>
<p>函数返回值是一个整数，取值范围在0到 <em>parties</em> -- 1，在每个线程中的返回值不相同。可用于从所有线程中选择唯一的一个线程执行一些特别的工作。例如：</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">i</span> <span class="o">=</span> <span class="n">barrier</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
<span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
    <span class="c1"># Only one thread needs to print this</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;passed the barrier&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>如果创建栅栏对象时在构造函数中提供了 <em>action</em> 参数，它将在其中一个线程释放前被调用。如果此调用引发了异常，栅栏对象将进入损坏态。</p>
<p>如果发生了超时，栅栏对象将进入破损态。</p>
<p>如果栅栏对象进入破损态，或重置栅栏时仍有线程等待释放，将会引发 <a class="reference internal" href="#threading.BrokenBarrierError" title="threading.BrokenBarrierError"><code class="xref py py-class docutils literal notranslate"><span class="pre">BrokenBarrierError</span></code></a> 异常。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Barrier.reset">
<code class="descname">reset</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Barrier.reset" title="永久链接至目标">¶</a></dt>
<dd><p>重置栅栏为默认的初始态。如果栅栏中仍有线程等待释放，这些线程将会收到 <a class="reference internal" href="#threading.BrokenBarrierError" title="threading.BrokenBarrierError"><code class="xref py py-class docutils literal notranslate"><span class="pre">BrokenBarrierError</span></code></a> 异常。</p>
<p>注意使用此函数时，如果有某些线程状态未知，则可能需其它的同步来确保线程已被释放。如果栅栏进入了破损态，最好废弃它并新建一个栅栏。</p>
</dd></dl>

<dl class="method">
<dt id="threading.Barrier.abort">
<code class="descname">abort</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#threading.Barrier.abort" title="永久链接至目标">¶</a></dt>
<dd><p>使栅栏进入破损态。这将导致所有已经调用和未来调用的 <a class="reference internal" href="#threading.Barrier.wait" title="threading.Barrier.wait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">wait()</span></code></a> 方法中引发 <a class="reference internal" href="#threading.BrokenBarrierError" title="threading.BrokenBarrierError"><code class="xref py py-class docutils literal notranslate"><span class="pre">BrokenBarrierError</span></code></a> 异常。使用这个方法的一种情况是需要中止程序以避免死锁。</p>
<p>更好的方式是：创建栅栏时提供一个合理的超时时间，来自动避免某个线程出错。</p>
</dd></dl>

<dl class="attribute">
<dt id="threading.Barrier.parties">
<code class="descname">parties</code><a class="headerlink" href="#threading.Barrier.parties" title="永久链接至目标">¶</a></dt>
<dd><p>冲出栅栏所需要的线程数量。</p>
</dd></dl>

<dl class="attribute">
<dt id="threading.Barrier.n_waiting">
<code class="descname">n_waiting</code><a class="headerlink" href="#threading.Barrier.n_waiting" title="永久链接至目标">¶</a></dt>
<dd><p>当前时刻正在栅栏中阻塞的线程数量。</p>
</dd></dl>

<dl class="attribute">
<dt id="threading.Barrier.broken">
<code class="descname">broken</code><a class="headerlink" href="#threading.Barrier.broken" title="永久链接至目标">¶</a></dt>
<dd><p>一个布尔值，值为 <code class="docutils literal notranslate"><span class="pre">True</span></code> 表明栅栏为破损态。</p>
</dd></dl>

</dd></dl>

<dl class="exception">
<dt id="threading.BrokenBarrierError">
<em class="property">exception </em><code class="descclassname">threading.</code><code class="descname">BrokenBarrierError</code><a class="headerlink" href="#threading.BrokenBarrierError" title="永久链接至目标">¶</a></dt>
<dd><p>异常类，是 <a class="reference internal" href="exceptions.html#RuntimeError" title="RuntimeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">RuntimeError</span></code></a> 异常的子类，在 <a class="reference internal" href="#threading.Barrier" title="threading.Barrier"><code class="xref py py-class docutils literal notranslate"><span class="pre">Barrier</span></code></a> 对象重置时仍有线程阻塞时和对象进入破损态时被引发。</p>
</dd></dl>

</div>
<div class="section" id="using-locks-conditions-and-semaphores-in-the-with-statement">
<span id="with-locks"></span><h2>在 <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code> 语句中使用锁、条件和信号量<a class="headerlink" href="#using-locks-conditions-and-semaphores-in-the-with-statement" title="永久链接至标题">¶</a></h2>
<p>这个模块提供的带有 <code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code> 和 <code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code> 方法的对象，可以被用作 <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> 语句的上下文管理器。当进入语句块时 <code class="xref py py-meth docutils literal notranslate"><span class="pre">acquire()</span></code> 方法会被调用，退出语句块时 <code class="xref py py-meth docutils literal notranslate"><span class="pre">release()</span></code>&nbsp;会被调用。因此，以下片段:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="n">some_lock</span><span class="p">:</span>
    <span class="c1"># do something...</span>
</pre></div>
</div>
<p>相当于:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">some_lock</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
    <span class="c1"># do something...</span>
<span class="k">finally</span><span class="p">:</span>
    <span class="n">some_lock</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
</pre></div>
</div>
<p>现在 <a class="reference internal" href="#threading.Lock" title="threading.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">Lock</span></code></a> 、 <a class="reference internal" href="#threading.RLock" title="threading.RLock"><code class="xref py py-class docutils literal notranslate"><span class="pre">RLock</span></code></a> 、 <a class="reference internal" href="#threading.Condition" title="threading.Condition"><code class="xref py py-class docutils literal notranslate"><span class="pre">Condition</span></code></a> 、 <a class="reference internal" href="#threading.Semaphore" title="threading.Semaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">Semaphore</span></code></a> 和 <a class="reference internal" href="#threading.BoundedSemaphore" title="threading.BoundedSemaphore"><code class="xref py py-class docutils literal notranslate"><span class="pre">BoundedSemaphore</span></code></a> 对象可以用作 <a class="reference internal" href="../reference/compound_stmts.html#with"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code></a> 语句的上下文管理器。</p>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#"><code class="docutils literal notranslate"><span class="pre">threading</span></code> --- 基于线程的并发</a><ul>
<li><a class="reference internal" href="#thread-local-data">线程本地数据</a></li>
<li><a class="reference internal" href="#thread-objects">线程对象</a></li>
<li><a class="reference internal" href="#lock-objects">锁对象</a></li>
<li><a class="reference internal" href="#rlock-objects">递归锁对象</a></li>
<li><a class="reference internal" href="#condition-objects">条件对象</a></li>
<li><a class="reference internal" href="#semaphore-objects">信号量对象</a><ul>
<li><a class="reference internal" href="#semaphore-example"><code class="docutils literal notranslate"><span class="pre">Semaphore</span></code> 例子</a></li>
</ul>
</li>
<li><a class="reference internal" href="#event-objects">事件对象</a></li>
<li><a class="reference internal" href="#timer-objects">定时器对象</a></li>
<li><a class="reference internal" href="#barrier-objects">栅栏对象</a></li>
<li><a class="reference internal" href="#using-locks-conditions-and-semaphores-in-the-with-statement">在 <code class="xref std std-keyword docutils literal notranslate"><span class="pre">with</span></code> 语句中使用锁、条件和信号量</a></li>
</ul>
</li>
</ul>

  <h4>上一个主题</h4>
  <p class="topless"><a href="concurrency.html"
                        title="上一章">并发执行</a></p>
  <h4>下一个主题</h4>
  <p class="topless"><a href="multiprocessing.html"
                        title="下一章"><code class="docutils literal notranslate"><span class="pre">multiprocessing</span></code> --- Process-based parallelism</a></p>
  <div role="note" aria-label="source link">
    <h3>本页</h3>
    <ul class="this-page-menu">
      <li><a href="../bugs.html">提交 Bug</a></li>
      <li>
        <a href="https://github.com/python/cpython/blob/3.7/Doc/library/threading.rst"
            rel="nofollow">显示源代码
        </a>
      </li>
    </ul>
  </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>  
    <div class="related" role="navigation" aria-label="related navigation">
      <h3>导航</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="总目录"
             >索引</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python 模块索引"
             >模块</a> |</li>
        <li class="right" >
          <a href="multiprocessing.html" title="multiprocessing --- Process-based parallelism"
             >下一页</a> |</li>
        <li class="right" >
          <a href="concurrency.html" title="并发执行"
             >上一页</a> |</li>
        <li><img src="../_static/py.png" alt=""
                 style="vertical-align: middle; margin-top: -1px"/></li>
        <li><a href="https://www.python.org/">Python</a> &#187;</li>
        <li>
          <span class="language_switcher_placeholder">zh_CN</span>
          <span class="version_switcher_placeholder">3.7.3</span>
          <a href="../index.html">文档</a> &#187;
        </li>

          <li class="nav-item nav-item-1"><a href="index.html" >Python 标准库</a> &#187;</li>
          <li class="nav-item nav-item-2"><a href="concurrency.html" >并发执行</a> &#187;</li>
    <li class="right">
        

    <div class="inline-search" style="display: none" role="search">
        <form class="inline-search" action="../search.html" method="get">
          <input placeholder="快速搜索" type="text" name="q" />
          <input type="submit" value="转向" />
          <input type="hidden" name="check_keywords" value="yes" />
          <input type="hidden" name="area" value="default" />
        </form>
    </div>
    <script type="text/javascript">$('.inline-search').show(0);</script>
         |
    </li>

      </ul>
    </div>  
    <div class="footer">
    &copy; <a href="../copyright.html">版权所有</a> 2001-2019, Python Software Foundation.
    <br />
    Python 软件基金会是一个非盈利组织。
    <a href="https://www.python.org/psf/donations/">请捐助。</a>
    <br />
    最后更新于 4月 09, 2019.
    <a href="../bugs.html">发现了问题</a>？
    <br />
    使用<a href="http://sphinx.pocoo.org/">Sphinx</a>1.8.4 创建。
    </div>

  </body>
</html>